#include "lib/decoders/oggvorbis/pvmvoicesourceoggvorbis.h"
#ifdef I3D_PLATFORM_S3E
#include "lib/decoders/caching/pvmvoicecaching.h"
#endif

#include "lib/memory/pvmmemory.h"

PVMVoiceSourceOggVorbis::PVMVoiceSourceOggVorbis()
{
	dataSource = NULL;
	vInfo = NULL;

	PVMInitCritical(&critical);
}

PVMVoiceSourceOggVorbis::~PVMVoiceSourceOggVorbis()
{
	if(dataSource)
		dataSource->Release();

	dataSource = NULL;
	vInfo = NULL;
	PVMDeinitCritical(&critical);
}

IPVMVoice* PVMVoiceSourceOggVorbis::CreateVoice(pvm_int samplesPerSecond, pvm_int bitsPerSample, pvm_int chanelsNum)
{
	IPVMVoice *newChanel = NULL;
	PVMOVDataSource* crateDataSource = dataSource;

	PVMEnterCritical(&critical);
	if(dataSource->GetRefCount()>1)
	{
		crateDataSource = PVMOVDataSource::Create(&dataSource->Stream(), true);
		if(crateDataSource==NULL)
		{
			PVMLeaveCritical(&critical);
			return NULL;
		}
	}
	else
	{
		pvm_int64 pcm_time = ov_pcm_tell(&(crateDataSource->OVFile()));

		if(pcm_time!=OV_EINVAL&&pcm_time!=0)
		{
			ov_raw_seek(&(crateDataSource->OVFile()), 0);
		}
	}

	newChanel = PVMVoiceOggVorbis::Create(crateDataSource, samplesPerSecond, bitsPerSample, chanelsNum);
	PVMLeaveCritical(&critical);
//#ifdef I3D_PLATFORM_S3E
//	newChanel = PVMVoiceCaching::Create(newChanel, 50, 100, 12);
//#endif
	return newChanel;
}

void PVMVoiceSourceOggVorbis::Destroy()
{
	delete( this);
}

pvm_int PVMVoiceSourceOggVorbis::GetLengthMS()
{
	if(!dataSource)
		return -1;

	pvm_int64 pcm_total = ov_pcm_total(&(dataSource->OVFile()), -1);
	if(pcm_total==OV_EINVAL)
		return -1;
	pvm_int ret = (pvm_int)((((double)pcm_total)/vInfo->rate)*1000);
	return ret;
}

PVMVoiceSourceOggVorbis* PVMVoiceSourceOggVorbis::Create(IPvmInStream* inStream)
{
	PVMOVDataSource* crateDataSource = PVMOVDataSource::Create(inStream, false);

	if(!crateDataSource)
		return NULL;

	crateDataSource->AddRef();

	PVMVoiceSourceOggVorbis* newSrc = new PVMVoiceSourceOggVorbis();

	if(!newSrc)
	{
		crateDataSource->Release();
		return NULL;
	}

	newSrc->dataSource = crateDataSource;
	newSrc->vInfo = ov_info(&(crateDataSource->OVFile()), -1);
	return newSrc;
}

pvm_bool PVMVoiceSourceOggVorbis::GetOption(const pvm_char* /*optionName*/, void* /*optionVal*/, pvm_uint32* /*optionSize*/)
{
	return false;
}

pvm_bool PVMVoiceSourceOggVorbis::SetOption(const pvm_char* /*optionName*/, void* /*optionVal*/, pvm_uint32 /*optionSize*/)
{
	return false;
}
